package org.benben;

import java.util.regex.*;
import java.util.*;

public class HtmlParser
{
    private String data;
    private String result;
    private DomTree domTree;
    private boolean isInTag;
    private boolean isInScript;
    private StringBuilder strBuilder;
    private int currentIndex;
    //private String [] tagToken
    private DomNode root;
    private ArrayList<String> hrefList;
    
    public HtmlParser()
    {
        data = result = "";
        domTree = new DomTree();
        this.currentIndex = 0;
        this.isInTag = this.isInScript = false;
        this.root = null;
        this.hrefList = new ArrayList<String>();
    }
    
    public HtmlParser(String data)
    {
        this.data = data;
        result = "";
    }
    
    public boolean isScript(String s)
    {
        return false;
    }
    
    public boolean isComment(String s)
    {
        return s.startsWith("<!--") || s.startsWith("!--");
    }
    
    public String getNextTag()
    {
        StringBuilder stringBuilder = new StringBuilder();
        
        int index = strBuilder.indexOf("<");
        
        if(index < 0)
            return "";
        
        ++index;
        while(index < strBuilder.length())
        {
            char ch = strBuilder.charAt(index);
            if(ch != '>')
            {    
                stringBuilder.append(ch);
                ++index;
            }
            else break;
        }
        
        //System.out.println("ch = " + strBuilder.charAt(index));
        //stringBuilder.append('>');
        //System.out.println("before:" + strBuilder.toString());
        String result = stringBuilder.toString().trim();
        //System.out.println("result:" + result);
        result = result.trim();
        if(result.startsWith("/script") == true)
            isInScript = false;
        if(result.startsWith("script") == true)
            isInScript = true;
        if(result.startsWith("/") == true)
            isInTag = false;
        if(result.endsWith("/") == true)
            isInTag = false;
        
        strBuilder.delete(0, index + 1);
        //
        //System.out.println("after:" + strBuilder.toString());
        return result;
    }
    
    public String getNextTag(String s)
    {
        StringBuilder stringBuilder = new StringBuilder();
        
        int index = s.indexOf("<");
        
        if(index < 0)
            return "";
        
        index++;
        while(index < s.length())
        {
            char ch = s.charAt(index);
            if(ch != '>')
            {    
                stringBuilder.append(ch);
                ++index;
            }
            else break;
        }
        
        //stringBuilder.append('>');
        
        String result = stringBuilder.toString();
        
        result = result.trim();
        if(result.startsWith("/script") == true)
            isInScript = false;
        if(result.startsWith("script") == true)
            isInScript = true;
        if(result.startsWith("/") == true)
            isInTag = false;
        if(result.endsWith("/") == true)
            isInTag = false;
                        
        return result;
    }
    
    public String getNextText()
    {
        StringBuilder result = new StringBuilder();
        
        int i = 0;
        
        //System.out.println("In srcipt:" + isInScript);
        if(isInScript == true)
        {
            while(i < strBuilder.length())
            {
                char ch = strBuilder.charAt(i);
                if(ch != '<')
                {
                    result.append(ch);
                    ++i;
                }
                else
                {
                    String script = "/script";
                    int len = script.length();
                    //strBuilder.substring(i, i)
                    //if(i < strBuilder.length() - 1 && strBuilder.charAt(i + 1) == '/')
                    //    break;
                    if(i < strBuilder.length() - len && strBuilder.charAt(i + 1) == '/')
                    {    
                        String temp = strBuilder.substring(i + 1, i + len + 1).trim();
                        //System.out.println("temp:" + temp);
                        if(temp.equals(script) == true)
                        {    
                            //i += len;
                            break;
                        }
                            else
                        {
                            result.append(ch);
                            ++i;
                        }
                        
                    }
                    else
                    {
                        result.append(ch);
                        ++i;
                    }
                }
            }
        }
        else
        {
            while(i < strBuilder.length())
            {   
                char ch = strBuilder.charAt(i);
                if(ch != '<')
                {    
                    result.append(ch);
                    ++i;
                }
                else
                    break;
            }
        }
        //System.out.println("ch:" + strBuilder.charAt(i));
        if(result.toString().trim().equals("") == false)
        {    
            //if(strBuilder.charAt(i) == '<')
                strBuilder.delete(0, i);
            //else
            //    strBuilder.delete(0, i + 1);
        }
        //System.out.println("str2:" + strBuilder.toString());
        return result.toString();
    }
    
    public String getNextText(String s)
    {
        StringBuilder result = new StringBuilder();
        
        if(isInScript == true)
        {
            int i = 0;
            while(i < s.length())
            {
                char ch = s.charAt(i);
                if(ch != '<')
                {
                    result.append(ch);
                    ++i;
                }
                else
                {
                    if(i < s.length() - 1 && s.charAt(i + 1) == '/')
                        break;
                    else
                    {
                        result.append(ch);
                        ++i;
                    }
                }
            }
        }
        else
        {
            int i = 0;
            while(i < s.length())
            {   
                char ch = s.charAt(i);
                if(ch != '<')
                {    
                    result.append(ch);
                    ++i;
                }
                else
                    break;
            }
        }
        
        return result.toString();
    }
    
    public String formatText(String s)
    {
        return null;
    }
    
    public String[] splitProperties(String s)
    {
        String regx = "[A-Za-z-1-9]+[ ]*=[ ]*\"[^\"]+\"";
        
        ArrayList<String> arrayList = new ArrayList<String>();
        
        StringBuilder stringBuilder = new StringBuilder();
        
        Pattern pattern = Pattern.compile(regx);
        Matcher matcher = pattern.matcher(s);
        
        while(matcher.find())
        {
            int start = matcher.start();
            int end = matcher.end();
            String subString = s.substring(start, end);
            
            int index = subString.indexOf("=");
            String key = subString.substring(0, index).trim();
            
            int index1 = subString.indexOf("\"");
            int index2 = subString.lastIndexOf("\"");
            
            String value = subString.substring(index1 + 1, index2).trim();
            
            String output = key + "=" + value;
            arrayList.add(output);
        }
        
        String [] result = (String [])arrayList.toArray();
        
        return result;
    }
    
    public HashMap<String, String> getProperties(String s)
    {
         HashMap<String, String> result = new HashMap<String, String>(); 
         boolean match = false;
         
         String regx = "[A-Za-z-1-9]+[ ]*=[ ]*\"[^\"]+\"";
         Pattern pattern = Pattern.compile(regx);
         Matcher matcher = pattern.matcher(s);
         
         while(matcher.find())
         {
             int start = matcher.start();
             int end = matcher.end();
             String keyValue = s.substring(start, end);
             
             int index = keyValue.indexOf("=");
             String key = keyValue.substring(0,index).trim();
             int index1 = keyValue.indexOf("\"");
             int index2 = keyValue.lastIndexOf("\"");
             String value = keyValue.substring(index1 + 1, index2).trim();
             
             result.put(key, value);
             
             match = true;
         }
         
         if(match == true)
            return result;
         else
            return null;
    }
    
    public HashMap<String, String> getProperty(String s)
    {
        HashMap<String, String> property = new HashMap<String, String>();
        
        int index = s.indexOf("=");
        
        if(index < 0)
            return null;
        
        String propertyName = s.substring(0, index).trim();
        
        int index1 = s.indexOf("\"");
        int index2 = s.lastIndexOf("\"");
        String value = s.substring(index1 + 1, index2).trim();
        
        property.put(propertyName, value);
        
        return property;
    }
    
    public void parse()
    {
        //ArrayList<String> hrefList = new ArrayList<String>();
        
        String tagName = "";
        
        while(strBuilder.length() > 0)
        {
            String nextTag = getNextTag();
            StringTokenizer tokenizer = new StringTokenizer(nextTag);
            
            if(tokenizer.countTokens() > 0)
                tagName = tokenizer.nextToken();
            else 
                tagName = "";
            //System.out.println("tag name:[" + tagName + "]");
            //System.out.println("tagName:" + tagName);
            //System.out.println("nextTag:[" + nextTag + "]");
            //System.out.println(strBuilder.toString());
            
            HashMap<String, String> propertyMap = getProperties(nextTag);
            
            
            if(tagName.equals("a") == true && propertyMap != null && propertyMap.containsKey("href") == true)
                this.hrefList.add(propertyMap.get("href"));
            /*
            if(tagName.equals("meta") == true)
            {
                if(propertyMap != null && propertyMap.containsKey("charset") == true)
                    ;
                System.out.println("charset:" + propertyMap.get("charset"));
                if(propertyMap != null && propertyMap.containsKey("name") == true)
                {    
                    String value = propertyMap.get("name");
                    if(value.equals("keywords"))
                    {
                        String [] keyWords = propertyMap.get("content").split(",");
                        System.out.print("keywords:[");
                        for(int i = 0;i < keyWords.length;++i)
                            System.out.print(keyWords[i] + "|");
                        System.out.println("]");
                    }
                    if(value.equals("description") == true)
                    {
                        String description = propertyMap.get("content");
                        System.out.println("Discription:" + description);
                    }
                }
                
            }
            */  
            //System.out.println("property:" + propertyMap);
            //strBuilder.delete(0, nextTag.length());
            //System.out.println(strBuilder.toString());
            //if(isInTag == false)
            String nextText = getNextText();
            nextText = Utils.replaceSpecialSymbol(nextText).trim();
            //strBuilder.delete(0, nextText.length());
            //if(nextText.equals("") == false)
            //    System.out.println("nextText:[" + nextText.trim() + "]");
            
            DomNode domNode = new DomNode();
            domNode.setProperty(propertyMap);
            domNode.setTagName(tagName);
            domNode.setValue(nextText);
            domNode.setNextSibling(null);
            domNode.setParent(null);
            domNode.setLeftChild(domNode);
            
            if(this.root == null)
                this.root = domNode;
        }
        
        //System.out.println("href list:" + this.hrefList.size());
        //for(int i = 0;i < this.hrefList.size();++i)
        //    System.out.println(this.hrefList.get(i));
        
        System.out.println("total url:" + this.hrefList.size() + "");
    }
    
    public String[] getHyperLinks()
    {
        //ArrayList<String> result = new ArrayList<String>();
        
        //for(int i = 0;i < this.hrefList.size();++i)
        //    result.add(this.hrefList.get(i).trim());
        int hrefListSize = this.hrefList.size();
        
        String [] result = new String[hrefListSize];
        for(int i = 0;i < hrefListSize;++i)
            result[i] = this.hrefList.get(i);
        
        return result;
    }
    
    public void parse2()
    {
        StringBuilder stringBuilder = new StringBuilder();
        
        int i = 0;
        boolean inTag = false;
        boolean inScript = false;
        
        while(i < data.length())
        {
            if(data.charAt(i) == '<')
            {
                String tagName = "";
                ++i;
                while(i < data.length() && data.charAt(i) == ' ')
                    ++i;
                                
                while(i < data.length() && data.charAt(i) != ' ' && data.charAt(i) != '>')
                {    
                    tagName += data.charAt(i);
                    
                    ++i;
                }
                if(i < data.length() && data.charAt(i) == '>')
                {    
                    inTag = false;
                     if(tagName.equals("script") == true)
                    inScript = true;
                if(tagName.equals("/script") == true)
                    inScript = false;
                    ++i;
                    continue;
                }
                System.out.println("tag " + tagName);
               
                inTag = true;
         
            }
            else if(data.charAt(i) == '>')
            {
                inTag = false;
                //inScript = false;
                ++i;
                continue;
            }
            //System.out.println("intag:" + inTag + ",inscript:" + inScript);
            if(inTag == false && inScript == false)
            {   
                stringBuilder.append(data.charAt(i));
                System.out.println(stringBuilder.toString());
                ++i;
            }
            else
                ++i;
        }
        
        result = stringBuilder.toString();
        String reg = "[' '\t]+";
        Pattern p = Pattern.compile(reg);
        Matcher matcher = p.matcher(result);
        result = matcher.replaceAll(" ");
        
        reg = "\r";
        p = Pattern.compile(reg);
        matcher = p.matcher(result);
        result = matcher.replaceAll("");      
        
        reg = "[\n]+";
        p = Pattern.compile(reg);
        matcher = p.matcher(result);
        result = matcher.replaceAll("\n");   
    }   
    
    public String getResult()
    {
        return result;
    }
    
    public void setContent(String content)
    {
        this.data = content.trim();
        
        this.strBuilder = new StringBuilder(this.data);
    }
}

